package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

func typeof_demo(x interface{}) {
	// reflect.TypeOf() 获取反射的具体数据类型
	v := reflect.TypeOf(x)
	fmt.Printf("x: %v  type:%v", x, v)
	// kind
	fmt.Printf("	type name: %v  type kind:%v\n", v.Name(), v.Kind())
}

func valueof_demo(x interface{}) {
	v := reflect.ValueOf(x)
	k := v.Kind()
	switch k {
	case reflect.String:
		fmt.Printf("type is String value is %v\n", string(v.String()))
	case reflect.Int32:
		fmt.Printf("type is int32 value is %d\n", int32(v.Int()))
	}
}

func reflectSetValue(x interface{}) {
	v := reflect.ValueOf(x)
	// if v.Kind() == reflect.Int64 {
	// 	v.SetInt(200) // 函数传参永远是副本，这里会引发panic
	// }

	// 反射中使用专有的Elem()方法来获取指针对应的值。
	if v.Elem().Kind() == reflect.Int64 {
		v.Elem().SetInt(200)
	}
}

// 反射机制
func main() {
	typeof_demo(10)
	typeof_demo("abc")
	type person struct {
		name string
		age  int32
	}
	p := person{"张三", 18} // p属于什么类型？person类型? struct类型？
	typeof_demo(p)

	// 通过反射获取变量的值
	var n int32 = 18
	valueof_demo(n)
	valueof_demo("mmn")
	valueof_demo(p)

	// 通过反射设置变量的值
	var b int64 = 100
	reflectSetValue(&b)
	fmt.Printf("b: %v\n", b)
}
